<html>
 <head>
  <meta charset="utf-8"/>
  <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"/>
  <title>
   写一个每秒接收上百万数据包的程序到底有多难？  | 数螺 | NAUT IDEA
  </title>
  <link href="http://cdn.bootcss.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" rel="stylesheet"/>
  <link href="http://cdn.bootcss.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
  <style type="text/css">
   #xmain img {
                  max-width: 100%;
                  display: block;
                  margin-top: 10px;
                  margin-bottom: 10px;
                }

                #xmain p {
                    line-height:150%;
                    font-size: 16px;
                    margin-top: 20px;
                }

                #xmain h2 {
                    font-size: 24px;
                }

                #xmain h3 {
                    font-size: 20px;
                }

                #xmain h4 {
                    font-size: 18px;
                }


                .header {
	           background-color: #0099ff;
	           color: #ffffff;
	           margin-bottom: 20px;
	        }

	        .header p {
                  margin: 0px;
                  padding: 10px 0;
                  display: inline-block;  
                  vertical-align: middle;
                  font-size: 16px;
               }

               .header a {
                 color: white;
               }

              .header img {
                 height: 25px;
              }
  </style>
  <script src="http://cdn.bootcss.com/jquery/3.0.0/jquery.min.js">
  </script>
  <script src="http://nautstatic-10007657.file.myqcloud.com/static/css/readability.min.js" type="text/javascript">
  </script>
  <script type="text/javascript">
   $(document).ready(function() {
                 var loc = document.location;
                 var uri = {
                  spec: "http://dataunion.org/19795.html",
                  host: "http://dataunion.org",
                  prePath: "http://dataunion.org",
                  scheme: "http",
                  pathBase: "http://dataunion.org/"
                 };
    
                 var documentClone = document.cloneNode(true);
                 var article = new Readability(uri, documentClone).parse();
     
                 document.getElementById("xmain").innerHTML = article.content;
                });
  </script>
  <!-- 1466454566: Accept with keywords: (title(0.25):程序,社区,数据包,数盟, topn(0.166666666667):社区,队列,端口,数盟,堆栈,系统,数据挖掘,职业规划,基础架构,文章,数据包,节点,内核,字节,性能,目的,接收者,网卡,算法,哈希,进程,接收端,核心,程序,网络,方法,行业资讯,描述符,线程,处理器).-->
 </head>
 <body onload="">
  <div class="header">
   <div class="container">
    <div class="row">
     <div class="col-xs-6 col-sm-6 text-left">
      <a href="/databee">
       <img src="http://nautidea-10007657.cos.myqcloud.com/logo_white.png"/>
      </a>
      <a href="/databee">
       <p>
        数螺
       </p>
      </a>
     </div>
     <div class="hidden-xs col-sm-6 text-right">
      <p>
       致力于数据科学的推广和知识传播
      </p>
     </div>
    </div>
   </div>
  </div>
  <div class="container text-center">
   <h1>
    写一个每秒接收上百万数据包的程序到底有多难？
   </h1>
  </div>
  <div class="container" id="xmain">
   ﻿﻿
   <title>
    写一个每秒接收上百万数据包的程序到底有多难？ | 数盟社区
   </title>
   <!-- All in One SEO Pack 2.2.7.6.2 by Michael Torbert of Semper Fi Web Design[32,69] -->
   <!-- /all in one seo pack -->
   <!--
<div align="center">
<a href="http://strata.oreilly.com.cn/hadoop-big-data-cn?cmp=mp-data-confreg-home-stcn16_dataunion_pc" target="_blank"><img src="http://dataunion.org/wp-content/uploads/2016/05/stratabj.jpg"/ ></a>
</div>
-->
   <header id="header-web">
    <div class="header-main">
     <hgroup class="logo">
      <h1>
       <a href="http://dataunion.org/" rel="home" title="数盟社区">
        <img src="http://dataunion.org/wp-content/themes/yzipi/images/logo.png"/>
       </a>
      </h1>
     </hgroup>
     <!--logo-->
     <nav class="header-nav">
      <ul class="menu" id="menu-%e4%b8%bb%e8%8f%9c%e5%8d%95">
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-has-children menu-item-71" id="menu-item-71">
        <a href="http://dataunion.org/category/events" title="events">
         活动
        </a>
        <ul class="sub-menu">
         <li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-22457" id="menu-item-22457">
          <a href="http://dataunion.org/2016timeline">
           2016档期
          </a>
         </li>
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-22459" id="menu-item-22459">
          <a href="http://dataunion.org/category/parterc">
           合作会议
          </a>
         </li>
        </ul>
       </li>
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category current-post-ancestor current-menu-parent current-post-parent menu-item-has-children menu-item-20869" id="menu-item-20869">
        <a href="http://dataunion.org/category/tech" title="articles">
         文章
        </a>
        <ul class="sub-menu">
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-20867" id="menu-item-20867">
          <a href="http://dataunion.org/category/tech/base" title="base">
           基础架构
          </a>
         </li>
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-3302" id="menu-item-3302">
          <a href="http://dataunion.org/category/tech/ai" title="ai">
           人工智能
          </a>
         </li>
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-3303" id="menu-item-3303">
          <a href="http://dataunion.org/category/tech/analysis" title="analysis">
           数据分析
          </a>
         </li>
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-21920" id="menu-item-21920">
          <a href="http://dataunion.org/category/tech/dm">
           数据挖掘
          </a>
         </li>
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-3314" id="menu-item-3314">
          <a href="http://dataunion.org/category/tech/viz" title="viz">
           可视化
          </a>
         </li>
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-3305" id="menu-item-3305">
          <a href="http://dataunion.org/category/tech/devl" title="devl">
           编程语言
          </a>
         </li>
        </ul>
       </li>
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-has-children menu-item-20876" id="menu-item-20876">
        <a href="http://dataunion.org/category/industry">
         行业
        </a>
        <ul class="sub-menu">
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-16328" id="menu-item-16328">
          <a href="http://dataunion.org/category/industry/case" title="case">
           行业应用
          </a>
         </li>
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2112" id="menu-item-2112">
          <a href="http://dataunion.org/category/industry/demo" title="demo">
           Demo展示
          </a>
         </li>
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-21562" id="menu-item-21562">
          <a href="http://dataunion.org/category/industry/news">
           行业资讯
          </a>
         </li>
        </ul>
       </li>
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-311" id="menu-item-311">
        <a href="http://dataunion.org/category/sources" title="sources">
         资源
        </a>
       </li>
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-20870" id="menu-item-20870">
        <a href="http://dataunion.org/category/books" title="book">
         图书
        </a>
       </li>
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-21363" id="menu-item-21363">
        <a href="http://dataunion.org/category/training">
         课程
        </a>
       </li>
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-has-children menu-item-21853" id="menu-item-21853">
        <a href="http://dataunion.org/category/jobs">
         职位
        </a>
        <ul class="sub-menu">
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-22050" id="menu-item-22050">
          <a href="http://dataunion.org/category/career">
           职业规划
          </a>
         </li>
        </ul>
       </li>
      </ul>
     </nav>
     <!--header-nav-->
    </div>
   </header>
   <!--header-web-->
   <div id="main">
    <div id="soutab">
     <form action="http://dataunion.org/" class="search" method="get">
     </form>
    </div>
    <div id="container">
     <nav id="mbx">
      当前位置：
      <a href="http://dataunion.org">
       首页
      </a>
      &gt;
      <a href="http://dataunion.org/category/tech">
       文章
      </a>
      &gt;  正文
     </nav>
     <!--mbx-->
     <article class="content">
      <header align="centre" class="contenttitle">
       <div class="mscc">
        <h1 class="mscctitle">
         <a href="http://dataunion.org/19795.html">
          写一个每秒接收上百万数据包的程序到底有多难？
         </a>
        </h1>
        <address class="msccaddress ">
         <em>
          2,082 次阅读 -
         </em>
         <a href="http://dataunion.org/category/tech" rel="category tag">
          文章
         </a>
        </address>
       </div>
      </header>
      <div class="content-text">
       <p>
        原文链接：
        <a href="https://blog.cloudflare.com/how-to-receive-a-million-packets/" target="_blank">
         How to receive a million packets per second
        </a>
        <br/>
        译文链接：
        <a href="https://www.jointforce.com/jfperiodical/article/show/821?m=d03" target="_blank">
         每秒如何接收上百万数据包
        </a>
        <br/>
        译者：曾越
       </p>
       <p>
        上周聊天的时候，我无意间听到一个同事说：”Linux网络堆栈（Linux network stack）太慢了！你不能指望它用一个CPU每秒处理50000个以上的数据包！”
       </p>
       <p>
        这引发了我深深的思考。我认同每个核心50kpps对任何实际的应用来说可能就是极限了，但Linux网络堆栈的能力只是如此吗？让我们换个角度来更有趣的叙述这件事。
       </p>
       <p>
       </p>
       <p>
        在Linux系统中，写一个能每秒接收1000000 UDP数据包的程序有多难？
       </p>
       <p>
        我希望，回答这个问题的过程，也能成就一篇关于现代网络堆栈设计的优秀教程。
       </p>
       <p>
       </p>
       <div align="center">
        <a href="https://www.jointforce.com/jfperiodical/article/show/821?m=d03" target="_blank">
         <img src="https://jf-bucket-public.oss-cn-qingdao.aliyuncs.com/jfperiodical/attached/image/20150624/1416004395.jpg"/>
        </a>
        <br/>
        <a href="https://creativecommons.org/licenses/by-sa/2.0/" target="_blank">
         CC BY-SA 2.0
        </a>
        image by
        <a href="https://www.flickr.com/photos/mccaffrey_uk" target="_blank">
         Bob McCaffrey
        </a>
       </div>
       <p>
        首先，让我们假设：
       </p>
       <ol>
        <li>
         ● 测量数据包每秒（packets per second 缩写pps）比测量字节每秒（bytes per second简写Bps）更有意义。你可以通过优化管道（piplelining）和发送更长的数据包来实现高Bps。但提高pps比这难得多。
        </li>
        <li>
         ● 既然我们对pps更感兴趣，我们的实验将会使用短UDP消息（short UDP messages）。更准确的说：32字节的UDP负载（UDP payload）。在以太网层（Ethernet layer）中是74字节。
        </li>
        <li>
         ● 在实验中我们会使用两个物理服务器：接受端（receiver）和发送端（sender）。
        </li>
        <li>
         ● 它们都配有2个6核2GHz的Xeon处理器。如果在每个核心上启用超线程技术（hyperthreading），则可分别模拟24个处理器。核心有一块Solarflare公司的多队列10G网卡（multi-queue 10G network card），已经配置了11个接收队列（receive queue）。更详细的之后讨论。
        </li>
        <li>
         ● 测试程序的源码可以从这里得到：
         <a href="https://github.com/majek/dump/blob/master/how-to-receive-a-million-packets/udpsender.c" target="_blank">
          udpsender
         </a>
         ，
         <a href="https://github.com/majek/dump/blob/master/how-to-receive-a-million-packets/udpreceiver1.c" target="_blank">
          udpreceiver
         </a>
         。
        </li>
       </ol>
       <p>
        <strong>
         准备 Prerequisites
        </strong>
       </p>
       <p>
        4321端口给UDP数据包。在开始之前，我们必须确保通信不会被iptables干扰。
       </p>
       <div>
        <div class="syntaxhighlighter js" id="highlighter_872061">
         <table border="0" cellpadding="0" cellspacing="0">
          <tbody>
           <tr>
            <td class="gutter">
             <div class="line number1 index0 alt2">
              1
             </div>
             <div class="line number2 index1 alt1">
              2
             </div>
            </td>
            <td class="code">
             <div class="container">
              <div class="line number1 index0 alt2">
               <code class="js plain">
                receiver$ iptables -I INPUT 1 -p udp --dport 4321 -j ACCEPT
               </code>
              </div>
              <div class="line number2 index1 alt1">
               <code class="js plain">
                receiver$ iptables -t raw -I PREROUTING 1 -p udp --dport 4321 -j NOTRACK
               </code>
              </div>
             </div>
            </td>
           </tr>
          </tbody>
         </table>
        </div>
       </div>
       <p>
        为了一会儿方便，先定义一些具体的的IP地址：
       </p>
       <div>
        <div class="syntaxhighlighter js" id="highlighter_423594">
         <table border="0" cellpadding="0" cellspacing="0">
          <tbody>
           <tr>
            <td class="gutter">
             <div class="line number1 index0 alt2">
              1
             </div>
             <div class="line number2 index1 alt1">
              2
             </div>
             <div class="line number3 index2 alt2">
              3
             </div>
             <div class="line number4 index3 alt1">
              4
             </div>
            </td>
            <td class="code">
             <div class="container">
              <div class="line number1 index0 alt2">
               <code class="js plain">
                receiver$
               </code>
               <code class="js keyword">
                for
               </code>
               <code class="js plain">
                i
               </code>
               <code class="js keyword">
                in
               </code>
               <code class="js plain">
                <code>
                 seq 1 20
                </code>
                ;
               </code>
               <code class="js keyword">
                do
               </code>
               <code class="js plain">
                \
               </code>
              </div>
              <div class="line number2 index1 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                ip addr add 192.168.254.$i/24 dev eth2; \
               </code>
              </div>
              <div class="line number3 index2 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                done
               </code>
              </div>
              <div class="line number4 index3 alt1">
               <code class="js plain">
                sender$ ip addr add 192.168.254.30/24 dev eth3
               </code>
              </div>
             </div>
            </td>
           </tr>
          </tbody>
         </table>
        </div>
       </div>
       <p>
        <strong>
         1.简单方法 The naive approach
        </strong>
       </p>
       <p>
        一开始先让我们做个最简单的实验。一次简单的发送和接收会传递多少个数据包呢？
        <br/>
        发送者的伪代码：
       </p>
       <div>
        <div class="syntaxhighlighter js" id="highlighter_376538">
         <table border="0" cellpadding="0" cellspacing="0">
          <tbody>
           <tr>
            <td class="gutter">
             <div class="line number1 index0 alt2">
              1
             </div>
             <div class="line number2 index1 alt1">
              2
             </div>
             <div class="line number3 index2 alt2">
              3
             </div>
             <div class="line number4 index3 alt1">
              4
             </div>
             <div class="line number5 index4 alt2">
              5
             </div>
            </td>
            <td class="code">
             <div class="container">
              <div class="line number1 index0 alt2">
               <code class="js plain">
                fd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
               </code>
              </div>
              <div class="line number2 index1 alt1">
               <code class="js plain">
                fd.bind((
               </code>
               <code class="js string">
                "0.0.0.0"
               </code>
               <code class="js plain">
                , 65400))
               </code>
               <code class="js preprocessor">
                # select source port to reduce nondeterminism
               </code>
              </div>
              <div class="line number3 index2 alt2">
               <code class="js plain">
                fd.connect((
               </code>
               <code class="js string">
                "192.168.254.1"
               </code>
               <code class="js plain">
                , 4321))
               </code>
              </div>
              <div class="line number4 index3 alt1">
               <code class="js keyword">
                while
               </code>
               <code class="js plain">
                True:
               </code>
              </div>
              <div class="line number5 index4 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                fd.sendmmsg([
               </code>
               <code class="js string">
                "\x00"
               </code>
               <code class="js plain">
                * 32] * 1024)
               </code>
              </div>
             </div>
            </td>
           </tr>
          </tbody>
         </table>
        </div>
       </div>
       <p>
        尽管我们可以使用常用的send系统调用，但它并不高效。内核的上下文切换将会有不小的消耗，最好极力避免它。幸运的是，一个方便的系统调用最近被加入到了Linux中：sendmmsg。它允许我们一次发送大量的数据包。让我们来试试1024个数据包。
        <br/>
        接受者的伪代码：
       </p>
       <div>
        <div class="syntaxhighlighter js" id="highlighter_125542">
         <table border="0" cellpadding="0" cellspacing="0">
          <tbody>
           <tr>
            <td class="gutter">
             <div class="line number1 index0 alt2">
              1
             </div>
             <div class="line number2 index1 alt1">
              2
             </div>
             <div class="line number3 index2 alt2">
              3
             </div>
             <div class="line number4 index3 alt1">
              4
             </div>
             <div class="line number5 index4 alt2">
              5
             </div>
            </td>
            <td class="code">
             <div class="container">
              <div class="line number1 index0 alt2">
               <code class="js plain">
                fd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
               </code>
              </div>
              <div class="line number2 index1 alt1">
               <code class="js plain">
                fd.bind((
               </code>
               <code class="js string">
                "0.0.0.0"
               </code>
               <code class="js plain">
                , 4321))
               </code>
              </div>
              <div class="line number3 index2 alt2">
               <code class="js keyword">
                while
               </code>
               <code class="js plain">
                True:
               </code>
              </div>
              <div class="line number4 index3 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                packets = [None] * 1024
               </code>
              </div>
              <div class="line number5 index4 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                fd.recvmmsg(packets, MSG_WAITFORONE)
               </code>
              </div>
             </div>
            </td>
           </tr>
          </tbody>
         </table>
        </div>
       </div>
       <p>
        类似地，
        <a href="http://man7.org/linux/man-pages/man2/recvmmsg.2.html" target="_blank">
         recvmmsg
        </a>
        也是recv系统调用的高效版本。
        <br/>
        让我们试一试：
       </p>
       <div>
        <div class="syntaxhighlighter js" id="highlighter_943256">
         <table border="0" cellpadding="0" cellspacing="0">
          <tbody>
           <tr>
            <td class="gutter">
             <div class="line number1 index0 alt2">
              1
             </div>
             <div class="line number2 index1 alt1">
              2
             </div>
             <div class="line number3 index2 alt2">
              3
             </div>
             <div class="line number4 index3 alt1">
              4
             </div>
             <div class="line number5 index4 alt2">
              5
             </div>
             <div class="line number6 index5 alt1">
              6
             </div>
             <div class="line number7 index6 alt2">
              7
             </div>
             <div class="line number8 index7 alt1">
              8
             </div>
             <div class="line number9 index8 alt2">
              9
             </div>
             <div class="line number10 index9 alt1">
              10
             </div>
            </td>
            <td class="code">
             <div class="container">
              <div class="line number1 index0 alt2">
               <code class="js plain">
                sender$ ./udpsender 192.168.254.1:4321
               </code>
              </div>
              <div class="line number2 index1 alt1">
               <code class="js plain">
                receiver$ ./udpreceiver1 0.0.0.0:4321
               </code>
              </div>
              <div class="line number3 index2 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                0.352M pps  10.730MiB /  90.010Mb
               </code>
              </div>
              <div class="line number4 index3 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                0.284M pps   8.655MiB /  72.603Mb
               </code>
              </div>
              <div class="line number5 index4 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                0.262M pps   7.991MiB /  67.033Mb
               </code>
              </div>
              <div class="line number6 index5 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                0.199M pps   6.081MiB /  51.013Mb
               </code>
              </div>
              <div class="line number7 index6 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                0.195M pps   5.956MiB /  49.966Mb
               </code>
              </div>
              <div class="line number8 index7 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                0.199M pps   6.060MiB /  50.836Mb
               </code>
              </div>
              <div class="line number9 index8 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                0.200M pps   6.097MiB /  51.147Mb
               </code>
              </div>
              <div class="line number10 index9 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                0.197M pps   6.021MiB /  50.509Mb
               </code>
              </div>
             </div>
            </td>
           </tr>
          </tbody>
         </table>
        </div>
       </div>
       <p>
        使用这种简单方法，我们可以达到197kpps和350kpps之间。不算太糟。不幸的是，并不稳定。内核会使我们的程序在CPU核心之间shuffle。给CPU固定进程会有些作用：
       </p>
       <div>
        <div class="syntaxhighlighter js" id="highlighter_920885">
         <table border="0" cellpadding="0" cellspacing="0">
          <tbody>
           <tr>
            <td class="gutter">
             <div class="line number1 index0 alt2">
              1
             </div>
             <div class="line number2 index1 alt1">
              2
             </div>
             <div class="line number3 index2 alt2">
              3
             </div>
             <div class="line number4 index3 alt1">
              4
             </div>
             <div class="line number5 index4 alt2">
              5
             </div>
             <div class="line number6 index5 alt1">
              6
             </div>
             <div class="line number7 index6 alt2">
              7
             </div>
             <div class="line number8 index7 alt1">
              8
             </div>
            </td>
            <td class="code">
             <div class="container">
              <div class="line number1 index0 alt2">
               <code class="js plain">
                sender$ taskset -c 1 ./udpsender 192.168.254.1:4321
               </code>
              </div>
              <div class="line number2 index1 alt1">
               <code class="js plain">
                receiver$ taskset -c 1 ./udpreceiver1 0.0.0.0:4321
               </code>
              </div>
              <div class="line number3 index2 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                0.362M pps  11.058MiB /  92.760Mb
               </code>
              </div>
              <div class="line number4 index3 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                0.374M pps  11.411MiB /  95.723Mb
               </code>
              </div>
              <div class="line number5 index4 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                0.369M pps  11.252MiB /  94.389Mb
               </code>
              </div>
              <div class="line number6 index5 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                0.370M pps  11.289MiB /  94.696Mb
               </code>
              </div>
              <div class="line number7 index6 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                0.365M pps  11.152MiB /  93.552Mb
               </code>
              </div>
              <div class="line number8 index7 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                0.360M pps  10.971MiB /  92.033Mb
               </code>
              </div>
             </div>
            </td>
           </tr>
          </tbody>
         </table>
        </div>
       </div>
       <p>
        现在，内核调度程序（kernel scheduler）把进程固定在指定的CPU上了。这改善了处理器缓存本地化（processor cache locality），使数据更稳定，这正是我们想要的。
       </p>
       <p>
        <strong>
         2.发送更多的数据包 Send more packets
        </strong>
       </p>
       <p>
        虽然370k pps对简单的程序并不算太糟，但离1Mpps的目标还很远。接受更多必然要发送更多。用2个独立的线程发送试试：
       </p>
       <div>
        <div class="syntaxhighlighter js" id="highlighter_835444">
         <table border="0" cellpadding="0" cellspacing="0">
          <tbody>
           <tr>
            <td class="gutter">
             <div class="line number1 index0 alt2">
              1
             </div>
             <div class="line number2 index1 alt1">
              2
             </div>
             <div class="line number3 index2 alt2">
              3
             </div>
             <div class="line number4 index3 alt1">
              4
             </div>
             <div class="line number5 index4 alt2">
              5
             </div>
             <div class="line number6 index5 alt1">
              6
             </div>
             <div class="line number7 index6 alt2">
              7
             </div>
            </td>
            <td class="code">
             <div class="container">
              <div class="line number1 index0 alt2">
               <code class="js plain">
                sender$ taskset -c 1,2 ./udpsender \
               </code>
              </div>
              <div class="line number2 index1 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                192.168.254.1:4321 192.168.254.1:4321
               </code>
              </div>
              <div class="line number3 index2 alt2">
               <code class="js plain">
                receiver$ taskset -c 1 ./udpreceiver1 0.0.0.0:4321
               </code>
              </div>
              <div class="line number4 index3 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                0.349M pps  10.651MiB /  89.343Mb
               </code>
              </div>
              <div class="line number5 index4 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                0.354M pps  10.815MiB /  90.724Mb
               </code>
              </div>
              <div class="line number6 index5 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                0.354M pps  10.806MiB /  90.646Mb
               </code>
              </div>
              <div class="line number7 index6 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                0.354M pps  10.811MiB /  90.690Mb
               </code>
              </div>
             </div>
            </td>
           </tr>
          </tbody>
         </table>
        </div>
       </div>
       <p>
        接受端的数量并没有增长。ethtool –S命令可以展示数据包的去向：
       </p>
       <div>
        <div class="syntaxhighlighter js" id="highlighter_182410">
         <table border="0" cellpadding="0" cellspacing="0">
          <tbody>
           <tr>
            <td class="gutter">
             <div class="line number1 index0 alt2">
              1
             </div>
             <div class="line number2 index1 alt1">
              2
             </div>
             <div class="line number3 index2 alt2">
              3
             </div>
             <div class="line number4 index3 alt1">
              4
             </div>
             <div class="line number5 index4 alt2">
              5
             </div>
             <div class="line number6 index5 alt1">
              6
             </div>
             <div class="line number7 index6 alt2">
              7
             </div>
             <div class="line number8 index7 alt1">
              8
             </div>
             <div class="line number9 index8 alt2">
              9
             </div>
             <div class="line number10 index9 alt1">
              10
             </div>
             <div class="line number11 index10 alt2">
              11
             </div>
             <div class="line number12 index11 alt1">
              12
             </div>
             <div class="line number13 index12 alt2">
              13
             </div>
            </td>
            <td class="code">
             <div class="container">
              <div class="line number1 index0 alt2">
               <code class="js plain">
                receiver$ watch
               </code>
               <code class="js string">
                'sudo ethtool -S eth2 |grep rx'
               </code>
              </div>
              <div class="line number2 index1 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                rx_nodesc_drop_cnt:    451.3k/s
               </code>
              </div>
              <div class="line number3 index2 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                rx-0.rx_packets:     8.0/s
               </code>
              </div>
              <div class="line number4 index3 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                rx-1.rx_packets:     0.0/s
               </code>
              </div>
              <div class="line number5 index4 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                rx-2.rx_packets:     0.0/s
               </code>
              </div>
              <div class="line number6 index5 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                rx-3.rx_packets:     0.5/s
               </code>
              </div>
              <div class="line number7 index6 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                rx-4.rx_packets:  355.2k/s
               </code>
              </div>
              <div class="line number8 index7 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                rx-5.rx_packets:     0.0/s
               </code>
              </div>
              <div class="line number9 index8 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                rx-6.rx_packets:     0.0/s
               </code>
              </div>
              <div class="line number10 index9 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                rx-7.rx_packets:     0.5/s
               </code>
              </div>
              <div class="line number11 index10 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                rx-8.rx_packets:     0.0/s
               </code>
              </div>
              <div class="line number12 index11 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                rx-9.rx_packets:     0.0/s
               </code>
              </div>
              <div class="line number13 index12 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                rx-10.rx_packets:    0.0/s
               </code>
              </div>
             </div>
            </td>
           </tr>
          </tbody>
         </table>
        </div>
       </div>
       <p>
       </p>
       <p>
        通过以上统计，NIC说明成功传递大约350kpps到RX-4号队列。 rx_nodesc_drop_cnt 是一个Solarflare公司特制的计数器，它报告NIC传送到内核时丢失450kpps。有时数据包传送失败的原因很隐晦。在我们的例子里它倒是很显眼：RX-4号队列传送数据包到CPU#4。CPU#4除了读取这350kpps的数据外，已经什么都做不了了。在htop中看看效果：
       </p>
       <div align="center">
        <a href="https://www.jointforce.com/jfperiodical/article/show/821?m=d03" target="_blank">
         <img src="https://jf-bucket-public.oss-cn-qingdao.aliyuncs.com/jfperiodical/attached/image/20150624/-1500416887.png"/>
        </a>
       </div>
       <p>
        <strong>
         多队列NIC速成 Crash course to multi-queue NICs
        </strong>
       </p>
       <p>
        传统地，网卡有一个用于在硬件和内核间传递数据包的RX队列。这个设计有明显的局限性——数据包的传送量不能超过一个CPU的处理上限。为了更好的利用多核系统，NIC开始支持多RX队列。设计很简单：每一个RX队列绑定一个单独的CPU，这样传送数据包给所有的RX队列，NIC就可以利用所有的CPU资源。但有一个问题：给定一个数据包，NIC如何确定推送到哪一个RX队列呢？
       </p>
       <div align="center">
        <a href="https://www.jointforce.com/jfperiodical/article/show/821?m=d03" target="_blank">
         <img src="https://jf-bucket-public.oss-cn-qingdao.aliyuncs.com/jfperiodical/attached/image/20150624/1337855540.png"/>
        </a>
       </div>
       <p>
        不能使用Round-robin均衡，因为它可能会把一个连接中的数据包重排序。一个替代方案是：通过数据包的hash来决定RX队列。hash来自元组（源IP，目的IP，源端口，目的端口）。这能保证一个流中的数据包总是在同一个RX队列中结束，不可能发生某个流中的数据包重排序。
       </p>
       <p>
        在我们的例子中，hash可以这样使用：
       </p>
       <div>
        <div class="syntaxhighlighter js" id="highlighter_735655">
         <table border="0" cellpadding="0" cellspacing="0">
          <tbody>
           <tr>
            <td class="gutter">
             <div class="line number1 index0 alt2">
              1
             </div>
            </td>
            <td class="code">
             <div class="container">
              <div class="line number1 index0 alt2">
               <code class="js plain">
                RX_queue_number = hash(
               </code>
               <code class="js string">
                '192.168.254.30'
               </code>
               <code class="js plain">
                ,
               </code>
               <code class="js string">
                '192.168.254.1'
               </code>
               <code class="js plain">
                , 65400, 4321) % number_of_queues
               </code>
              </div>
             </div>
            </td>
           </tr>
          </tbody>
         </table>
        </div>
       </div>
       <p>
        <strong>
         多队列哈希算法 Multi-queue hashing algorithms
        </strong>
       </p>
       <p>
        哈希算法可以使用ethtool设置。我们的设置如下：
       </p>
       <div>
        <div class="syntaxhighlighter js" id="highlighter_579093">
         <table border="0" cellpadding="0" cellspacing="0">
          <tbody>
           <tr>
            <td class="gutter">
             <div class="line number1 index0 alt2">
              1
             </div>
             <div class="line number2 index1 alt1">
              2
             </div>
             <div class="line number3 index2 alt2">
              3
             </div>
             <div class="line number4 index3 alt1">
              4
             </div>
            </td>
            <td class="code">
             <div class="container">
              <div class="line number1 index0 alt2">
               <code class="js plain">
                receiver$ ethtool -n eth2 rx-flow-hash udp4
               </code>
              </div>
              <div class="line number2 index1 alt1">
               <code class="js plain">
                UDP over IPV4 flows use these fields
               </code>
               <code class="js keyword">
                for
               </code>
               <code class="js plain">
                computing Hash flow key:
               </code>
              </div>
              <div class="line number3 index2 alt2">
               <code class="js plain">
                IP SA
               </code>
              </div>
              <div class="line number4 index3 alt1">
               <code class="js plain">
                IP DA
               </code>
              </div>
             </div>
            </td>
           </tr>
          </tbody>
         </table>
        </div>
       </div>
       <p>
        以上的意思是：对IPV4的UDP数据包，NIC将计算哈希（源IP，目的IP）地址。例如：
       </p>
       <div>
        <div class="syntaxhighlighter js" id="highlighter_647">
         <table border="0" cellpadding="0" cellspacing="0">
          <tbody>
           <tr>
            <td class="gutter">
             <div class="line number1 index0 alt2">
              1
             </div>
            </td>
            <td class="code">
             <div class="container">
              <div class="line number1 index0 alt2">
               <code class="js plain">
                RX_queue_number = hash(
               </code>
               <code class="js string">
                '192.168.254.30'
               </code>
               <code class="js plain">
                ,
               </code>
               <code class="js string">
                '192.168.254.1'
               </code>
               <code class="js plain">
                ) % number_of_queues
               </code>
              </div>
             </div>
            </td>
           </tr>
          </tbody>
         </table>
        </div>
       </div>
       <p>
        因忽略了端口参数，这相当受限。大部分NIC允许自定义哈希方法。再使用ethtool选择元组（源IP，目的IP，源端口，目的端口）计算哈希：
       </p>
       <div>
        <div class="syntaxhighlighter js" id="highlighter_105324">
         <table border="0" cellpadding="0" cellspacing="0">
          <tbody>
           <tr>
            <td class="gutter">
             <div class="line number1 index0 alt2">
              1
             </div>
             <div class="line number2 index1 alt1">
              2
             </div>
            </td>
            <td class="code">
             <div class="container">
              <div class="line number1 index0 alt2">
               <code class="js plain">
                receiver$ ethtool -N eth2 rx-flow-hash udp4 sdfn
               </code>
              </div>
              <div class="line number2 index1 alt1">
               <code class="js plain">
                Cannot change RX network flow hashing options: Operation not supported
               </code>
              </div>
             </div>
            </td>
           </tr>
          </tbody>
         </table>
        </div>
       </div>
       <p>
        不幸的是，我们的NIC不支持——我们只好使用受限的（源IP,目的IP）哈希。
       </p>
       <p>
        <strong>
         非一致性内存访问性能注意事项 A note on NUMA performance
        </strong>
       </p>
       <p>
        目前为止，我们所有的数据流都分配给了一个RX队列，并且只匹配一个CPU。让我们以此为基础，来试试多CPU。在我们的配置中，接收端主机有两个单独的进程“仓库“，它们各是一个NUMA节点。
       </p>
       <p>
        我们将一个单线程接收端固定到4个CPU中的1个。四种情况分别是：
       </p>
       <ul>
        <li>
         1.在另一个CPU上运行接收端，但在同一个用于RX队列的NUMA节点上。如上文所述，性能大概是360kpps。
        </li>
        <li>
         2.使用同一个用于RX队列的CPU，性能大约是430kpps。但这很不稳定。如果NIC被数据包淹没了，性能可能会为0。
        </li>
        <li>
         3.当接收端运行在处理RX队列的CPU的HT部分，性能大概是平时的一半，也就是200kpps。
        </li>
        <li>
         4.当接收者在CPU和RX队列分别在不同的NUMA节点运行时，我们得到大致330kpps的数值。虽然这个数字不总是一致。
        </li>
       </ul>
       <p>
        尽管在不同NUMA节点上运行时， 10%的性能损失（penalty）似乎并不是太糟，但真正的问题是在扩展的时候。在一些测试场景中，我只能得到250kpps的结果。在所有跨NUMA的测试中，都很不稳定。跨NUMA节点的性能损失在高吞吐量场景中更常见。一次测试时，接收端运行在一个糟糕的NUMA节点上，我遭遇了4倍的性能损失。
       </p>
       <p>
        <strong>
         3.多重接收IP Multiple receive IPs
        </strong>
       </p>
       <p>
        因为哈希算法在我们的NIC上受限，唯一的解决方法是：跨RX队列，把数据包分发到不同的IP地址。下面是如何发送数据包到不同的目的IP：
       </p>
       <div>
        <div class="syntaxhighlighter js" id="highlighter_93917">
         <table border="0" cellpadding="0" cellspacing="0">
          <tbody>
           <tr>
            <td class="gutter">
             <div class="line number1 index0 alt2">
              1
             </div>
            </td>
            <td class="code">
             <div class="container">
              <div class="line number1 index0 alt2">
               <code class="js plain">
                sender$ taskset -c 1,2 ./udpsender 192.168.254.1:4321 192.168.254.2:4321
               </code>
              </div>
             </div>
            </td>
           </tr>
          </tbody>
         </table>
        </div>
       </div>
       <p>
        使用ethtool确保数据包分配给不同的RX队列：
       </p>
       <div>
        <div class="syntaxhighlighter js" id="highlighter_284053">
         <table border="0" cellpadding="0" cellspacing="0">
          <tbody>
           <tr>
            <td class="gutter">
             <div class="line number1 index0 alt2">
              1
             </div>
             <div class="line number2 index1 alt1">
              2
             </div>
             <div class="line number3 index2 alt2">
              3
             </div>
             <div class="line number4 index3 alt1">
              4
             </div>
             <div class="line number5 index4 alt2">
              5
             </div>
             <div class="line number6 index5 alt1">
              6
             </div>
             <div class="line number7 index6 alt2">
              7
             </div>
             <div class="line number8 index7 alt1">
              8
             </div>
             <div class="line number9 index8 alt2">
              9
             </div>
             <div class="line number10 index9 alt1">
              10
             </div>
             <div class="line number11 index10 alt2">
              11
             </div>
             <div class="line number12 index11 alt1">
              12
             </div>
            </td>
            <td class="code">
             <div class="container">
              <div class="line number1 index0 alt2">
               <code class="js plain">
                receiver$ watch
               </code>
               <code class="js string">
                'sudo ethtool -S eth2 |grep rx'
               </code>
              </div>
              <div class="line number2 index1 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                rx-0.rx_packets:     8.0/s
               </code>
              </div>
              <div class="line number3 index2 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                rx-1.rx_packets:     0.0/s
               </code>
              </div>
              <div class="line number4 index3 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                rx-2.rx_packets:     0.0/s
               </code>
              </div>
              <div class="line number5 index4 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                rx-3.rx_packets:  355.2k/s
               </code>
              </div>
              <div class="line number6 index5 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                rx-4.rx_packets:     0.5/s
               </code>
              </div>
              <div class="line number7 index6 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                rx-5.rx_packets:  297.0k/s
               </code>
              </div>
              <div class="line number8 index7 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                rx-6.rx_packets:     0.0/s
               </code>
              </div>
              <div class="line number9 index8 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                rx-7.rx_packets:     0.5/s
               </code>
              </div>
              <div class="line number10 index9 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                rx-8.rx_packets:     0.0/s
               </code>
              </div>
              <div class="line number11 index10 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                rx-9.rx_packets:     0.0/s
               </code>
              </div>
              <div class="line number12 index11 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                rx-10.rx_packets:    0.0/s
               </code>
              </div>
             </div>
            </td>
           </tr>
          </tbody>
         </table>
        </div>
       </div>
       <p>
        接收部分：
       </p>
       <div>
        <div class="syntaxhighlighter js" id="highlighter_176062">
         <table border="0" cellpadding="0" cellspacing="0">
          <tbody>
           <tr>
            <td class="gutter">
             <div class="line number1 index0 alt2">
              1
             </div>
             <div class="line number2 index1 alt1">
              2
             </div>
             <div class="line number3 index2 alt2">
              3
             </div>
             <div class="line number4 index3 alt1">
              4
             </div>
            </td>
            <td class="code">
             <div class="container">
              <div class="line number1 index0 alt2">
               <code class="js plain">
                receiver$ taskset -c 1 ./udpreceiver1 0.0.0.0:4321
               </code>
              </div>
              <div class="line number2 index1 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                0.609M pps  18.599MiB / 156.019Mb
               </code>
              </div>
              <div class="line number3 index2 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                0.657M pps  20.039MiB / 168.102Mb
               </code>
              </div>
              <div class="line number4 index3 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                0.649M pps  19.803MiB / 166.120Mb
               </code>
              </div>
             </div>
            </td>
           </tr>
          </tbody>
         </table>
        </div>
       </div>
       <p>
       </p>
       <p>
        万岁！两个核心全力处理RX队列，第三个运行应用，已达到了650Kpps！
       </p>
       <p>
        将流量分发到3-4个RX队列就可以进一步增加这个数字，但应用会遇到另一个瓶颈。这次rx_nodesc_drop_cnt没有增长，对应的netstat“接收者错误”：
       </p>
       <div>
        <div class="syntaxhighlighter js" id="highlighter_242663">
         <table border="0" cellpadding="0" cellspacing="0">
          <tbody>
           <tr>
            <td class="gutter">
             <div class="line number1 index0 alt2">
              1
             </div>
             <div class="line number2 index1 alt1">
              2
             </div>
             <div class="line number3 index2 alt2">
              3
             </div>
             <div class="line number4 index3 alt1">
              4
             </div>
             <div class="line number5 index4 alt2">
              5
             </div>
             <div class="line number6 index5 alt1">
              6
             </div>
             <div class="line number7 index6 alt2">
              7
             </div>
             <div class="line number8 index7 alt1">
              8
             </div>
             <div class="line number9 index8 alt2">
              9
             </div>
            </td>
            <td class="code">
             <div class="container">
              <div class="line number1 index0 alt2">
               <code class="js plain">
                receiver$ watch
               </code>
               <code class="js string">
                'netstat -s --udp'
               </code>
              </div>
              <div class="line number2 index1 alt1">
               <code class="js plain">
                Udp:
               </code>
              </div>
              <div class="line number3 index2 alt2">
               <code class="js plain">
                437.0k/s packets received
               </code>
              </div>
              <div class="line number4 index3 alt1">
               <code class="js plain">
                0.0/s packets to unknown port received.
               </code>
              </div>
              <div class="line number5 index4 alt2">
               <code class="js plain">
                386.9k/s packet receive errors
               </code>
              </div>
              <div class="line number6 index5 alt1">
               <code class="js plain">
                0.0/s packets sent
               </code>
              </div>
              <div class="line number7 index6 alt2">
               <code class="js plain">
                RcvbufErrors:  123.8k/s
               </code>
              </div>
              <div class="line number8 index7 alt1">
               <code class="js plain">
                SndbufErrors: 0
               </code>
              </div>
              <div class="line number9 index8 alt2">
               <code class="js plain">
                InCsumErrors: 0
               </code>
              </div>
             </div>
            </td>
           </tr>
          </tbody>
         </table>
        </div>
       </div>
       <p>
        上面这段话指出，虽然NIC能够传递数据包给内核，但内核不能够将数据包发送给应用。在我们的例子中，只成功发送了440kpps，其余的390kpps+123kpps被丢弃了，因为应用不足以接收他们。
       </p>
       <p>
        <strong>
         4.
         <strong>
          多线程接收
         </strong>
         Receive from many threads
        </strong>
       </p>
       <p>
        我们需要扩展接收端应用的能力。最初的、多线程的接收方法不会再有效了：
       </p>
       <div>
        <div class="syntaxhighlighter js" id="highlighter_348372">
         <table border="0" cellpadding="0" cellspacing="0">
          <tbody>
           <tr>
            <td class="gutter">
             <div class="line number1 index0 alt2">
              1
             </div>
             <div class="line number2 index1 alt1">
              2
             </div>
             <div class="line number3 index2 alt2">
              3
             </div>
             <div class="line number4 index3 alt1">
              4
             </div>
             <div class="line number5 index4 alt2">
              5
             </div>
             <div class="line number6 index5 alt1">
              6
             </div>
            </td>
            <td class="code">
             <div class="container">
              <div class="line number1 index0 alt2">
               <code class="js plain">
                sender$ taskset -c 1,2 ./udpsender 192.168.254.1:4321 192.168.254.2:4321
               </code>
              </div>
              <div class="line number2 index1 alt1">
               <code class="js plain">
                receiver$ taskset -c 1,2 ./udpreceiver1 0.0.0.0:4321 2
               </code>
              </div>
              <div class="line number3 index2 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                0.495M pps  15.108MiB / 126.733Mb
               </code>
              </div>
              <div class="line number4 index3 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                0.480M pps  14.636MiB / 122.775Mb
               </code>
              </div>
              <div class="line number5 index4 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                0.461M pps  14.071MiB / 118.038Mb
               </code>
              </div>
              <div class="line number6 index5 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                0.486M pps  14.820MiB / 124.322Mb
               </code>
              </div>
             </div>
            </td>
           </tr>
          </tbody>
         </table>
        </div>
       </div>
       <p>
        接收性能相比单线程程序要低。是因为在UDP接收缓冲区（UDP receive buffer side）出现的锁竞争（lock contention）。因为所有的线程使用同一个socket描述符（socket descriptor），它们在从UDP接收缓冲区获得锁的步骤上花费了不相称的时间（disproportionate amount of time）。
        <a href="http://www.jcc2014.ucm.cl/jornadas/WORKSHOP/WSDP%202014/WSDP-4.pdf" target="_blank">
         这里
        </a>
        详细描述了这个问题。
        <br/>
        使用多线程从一个描述符接收数据并不理想。
       </p>
       <p>
        <strong>
         5. SO_REUSEPORT
        </strong>
       </p>
       <p>
        幸运的是，最近有一项成果增加到了Linux中：
        <a href="https://lwn.net/Articles/542629/" target="_blank">
         SO_REUSEPORT
        </a>
        标志位。当在socket描述符上设置这个标志位时，Linux会允许多个进程绑定在同一个端口上。真实情况是，无论多少进程都将被允许绑定，且负载会被分担。
       </p>
       <p>
        设置 SO_REUSEPORT 的每个进程都会有一个独立的socket描述符。因此他们得到了一个专属UDP接收缓存（dedicated UDP receive buffer）。这就避免了之前遇到的竞争问题。
       </p>
       <div>
        <div class="syntaxhighlighter js" id="highlighter_808573">
         <table border="0" cellpadding="0" cellspacing="0">
          <tbody>
           <tr>
            <td class="gutter">
             <div class="line number1 index0 alt2">
              1
             </div>
             <div class="line number2 index1 alt1">
              2
             </div>
             <div class="line number3 index2 alt2">
              3
             </div>
             <div class="line number4 index3 alt1">
              4
             </div>
            </td>
            <td class="code">
             <div class="container">
              <div class="line number1 index0 alt2">
               <code class="js plain">
                receiver$ taskset -c 1,2,3,4 ./udpreceiver1 0.0.0.0:4321 4 1
               </code>
              </div>
              <div class="line number2 index1 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                1.114M pps  34.007MiB / 285.271Mb
               </code>
              </div>
              <div class="line number3 index2 alt2">
               <code class="js spaces">
               </code>
               <code class="js plain">
                1.147M pps  34.990MiB / 293.518Mb
               </code>
              </div>
              <div class="line number4 index3 alt1">
               <code class="js spaces">
               </code>
               <code class="js plain">
                1.126M pps  34.374MiB / 288.354Mb
               </code>
              </div>
             </div>
            </td>
           </tr>
          </tbody>
         </table>
        </div>
       </div>
       <p>
       </p>
       <p>
        这才像样！吞吐量现在不错了！
       </p>
       <p>
        如果你继续研究，还会有更大的改进空间。即使我们开了4个接收线程，负载也没有被平均分配到上面。
        <br/>
        2个线程接收了所有的数据，另外2个没有获得数据包。这应该是哈希冲突造成的，但这次问题出在SO_REUSEPORT 层。
       </p>
       <p>
        <strong>
         结语 Final words
        </strong>
       </p>
       <p>
        我又做了一些额外测试，完美的分配RX队列并将所有的接收线程都运行在一个NUMA节点上的话，可以达到1.4Mpps的性能。接收者运行在不同的NUMA节点上，即使性能略有下降，但也完成了1Mpps的目标。
       </p>
       <p>
        总结一下，如果你想要完美的性能，你需要：
       </p>
       <ul>
        <li>
         ● 保证流量被均分到每一个RX 队列和SO_REUSEPORT进程上。实践中，只要有大量的连接（流）负载，通常它们是能均匀分布的。
        </li>
        <li>
         ● 你需要有足够的空闲CPU才能从内核中获取数据包。
        </li>
        <li>
         ● 为了使性能更棒，RX队列和接收进程应该在一个NUMA节点上。
        </li>
       </ul>
       <p>
        我们证实了，技术上讲，在Linux机器上接收1Mpps是可能的，应用并没有做任何处理接收数据包的工作——它甚至也不关注流的内容。实际的应用中，为了达到这样的性能，还是需要做大量工作的。
       </p>
      </div>
      <div>
       <strong>
        注：转载文章均来自于公开网络，仅供学习使用，不会用于任何商业用途，如果侵犯到原作者的权益，请您与我们联系删除或者授权事宜，联系邮箱：contact@dataunion.org。转载数盟网站文章请注明原文章作者，否则产生的任何版权纠纷与数盟无关。
       </strong>
      </div>
      <!--content_text-->
      <div class="fenxian">
       <!-- JiaThis Button BEGIN -->
       <div class="jiathis_style_32x32">
        <p class="jiathis_button_weixin">
        </p>
        <p class="jiathis_button_tsina">
        </p>
        <p class="jiathis_button_qzone">
        </p>
        <p class="jiathis_button_cqq">
        </p>
        <p class="jiathis_button_tumblr">
        </p>
        <a class="jiathis jiathis_txt jtico jtico_jiathis" href="http://www.jiathis.com/share" target="_blank">
        </a>
        <p class="jiathis_counter_style">
        </p>
       </div>
       <!-- JiaThis Button END -->
      </div>
     </article>
     <!--content-->
     <!--相关文章-->
     <div class="xianguan">
      <div class="xianguantitle">
       相关文章！
      </div>
      <ul class="pic">
       <li>
        <a href="http://dataunion.org/20824.html">
         <img src="http://dataunion.org/wp-content/uploads/2015/09/t018630756a7e263b33-300x165.jpg"/>
        </a>
        <a class="link" href="http://dataunion.org/20824.html" rel="bookmark" title="如何判断一笔交易是否属于欺诈？你只是需要一点数据挖掘">
         如何判断一笔交易是否属于欺诈？你只是需要一点数据挖掘
        </a>
       </li>
       <li>
        <a href="http://dataunion.org/20820.html">
         <img src="http://dataunion.org/wp-content/uploads/2015/09/1-300x200.jpg"/>
        </a>
        <a class="link" href="http://dataunion.org/20820.html" rel="bookmark" title="人们对Python在企业级开发中的10大误解">
         人们对Python在企业级开发中的10大误解
        </a>
       </li>
       <li>
        <a href="http://dataunion.org/20811.html">
         <img src="http://dataunion.org/wp-content/uploads/2015/09/t0133fcacae8523307b_副本-300x200.jpg"/>
        </a>
        <a class="link" href="http://dataunion.org/20811.html" rel="bookmark" title="大神亲传：26条深度学习的金科玉律！">
         大神亲传：26条深度学习的金科玉律！
        </a>
       </li>
       <li>
        <a href="http://dataunion.org/20808.html">
         <img src="http://dataunion.org/wp-content/uploads/2015/09/640.webp-11-300x137.jpg"/>
        </a>
        <a class="link" href="http://dataunion.org/20808.html" rel="bookmark" title="我们是如何在一张地图上表现86万个数据的">
         我们是如何在一张地图上表现86万个数据的
        </a>
       </li>
      </ul>
     </div>
     <!--相关文章-->
     <div class="comment" id="comments">
      <!-- You can start editing here. -->
      <!-- If comments are open, but there are no comments. -->
      <div class="title">
       期待你一针见血的评论，Come on！
      </div>
      <div id="respond">
       <p>
        不用想啦，马上
        <a href="http://dataunion.org/wp-login.php?redirect_to=http%3A%2F%2Fdataunion.org%2F19795.html">
         "登录"
        </a>
        发表自已的想法.
       </p>
      </div>
     </div>
     <!-- .nav-single -->
    </div>
    <!--Container End-->
    <aside id="sitebar">
     <div class="sitebar_list2">
      <div class="wptag">
       <span class="tagtitle">
        热门标签+
       </span>
       <div class="tagg">
        <ul class="menu" id="menu-%e5%8f%8b%e6%83%85%e9%93%be%e6%8e%a5">
         <li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-1605" id="menu-item-1605">
          <a href="http://taidizh.com/">
           泰迪智慧
          </a>
         </li>
         <li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-20884" id="menu-item-20884">
          <a href="http://www.transwarp.cn/">
           星环科技
          </a>
         </li>
         <li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-3538" id="menu-item-3538">
          <a href="http://datall.org/">
           珈和遥感
          </a>
         </li>
         <li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-20888" id="menu-item-20888">
          <a href="http://www.chinahadoop.cn/">
           小象学院
          </a>
         </li>
        </ul>
       </div>
      </div>
     </div>
     <div class="sitebar_list">
      <div class="textwidget">
       <div align="center">
        <a href="http://study.163.com/course/courseMain.htm?courseId=991022" target="_blank">
         <img src="http://dataunion.org/wp-content/uploads/2016/03/dv.jpg"/>
        </a>
       </div>
      </div>
     </div>
     <div class="sitebar_list">
      <h4 class="sitebar_title">
       文章分类
      </h4>
      <div class="tagcloud">
       <a class="tag-link-44" href="http://dataunion.org/category/industry/demo" style="font-size: 10.204724409449pt;" title="4个话题">
        Demo展示
       </a>
       <a class="tag-link-31" href="http://dataunion.org/category/experts" style="font-size: 15.826771653543pt;" title="52个话题">
        专家团队
       </a>
       <a class="tag-link-870" href="http://dataunion.org/category/tech/ai" style="font-size: 19.795275590551pt;" title="273个话题">
        人工智能
       </a>
       <a class="tag-link-488" href="http://dataunion.org/category/%e5%8a%a0%e5%85%a5%e6%95%b0%e7%9b%9f" style="font-size: 8pt;" title="1个话题">
        加入数盟
       </a>
       <a class="tag-link-869" href="http://dataunion.org/category/tech/viz" style="font-size: 17.204724409449pt;" title="93个话题">
        可视化
       </a>
       <a class="tag-link-30" href="http://dataunion.org/category/partners" style="font-size: 10.645669291339pt;" title="5个话题">
        合作伙伴
       </a>
       <a class="tag-link-889" href="http://dataunion.org/category/parterc" style="font-size: 11.582677165354pt;" title="8个话题">
        合作会议
       </a>
       <a class="tag-link-104" href="http://dataunion.org/category/books" style="font-size: 12.96062992126pt;" title="15个话题">
        图书
       </a>
       <a class="tag-link-220" href="http://dataunion.org/category/tech/base" style="font-size: 19.850393700787pt;" title="281个话题">
        基础架构
       </a>
       <a class="tag-link-219" href="http://dataunion.org/category/tech/analysis" style="font-size: 19.409448818898pt;" title="232个话题">
        数据分析
       </a>
       <a class="tag-link-887" href="http://dataunion.org/category/tech/dm" style="font-size: 13.291338582677pt;" title="17个话题">
        数据挖掘
       </a>
       <a class="tag-link-34" href="http://dataunion.org/category/tech" style="font-size: 20.732283464567pt;" title="404个话题">
        文章
       </a>
       <a class="tag-link-1" href="http://dataunion.org/category/uncategorized" style="font-size: 22pt;" title="693个话题">
        未分类
       </a>
       <a class="tag-link-4" href="http://dataunion.org/category/events" style="font-size: 14.503937007874pt;" title="29个话题">
        活动
       </a>
       <a class="tag-link-890" href="http://dataunion.org/category/tech/%e6%b7%b1%e5%ba%a6%e5%ad%a6%e4%b9%a0" style="font-size: 10.204724409449pt;" title="4个话题">
        深度学习
       </a>
       <a class="tag-link-221" href="http://dataunion.org/category/tech/devl" style="font-size: 18.968503937008pt;" title="193个话题">
        编程语言
       </a>
       <a class="tag-link-888" href="http://dataunion.org/category/career" style="font-size: 15.661417322835pt;" title="48个话题">
        职业规划
       </a>
       <a class="tag-link-5" href="http://dataunion.org/category/jobs" style="font-size: 14.11811023622pt;" title="25个话题">
        职位
       </a>
       <a class="tag-link-871" href="http://dataunion.org/category/industry" style="font-size: 15.716535433071pt;" title="49个话题">
        行业
       </a>
       <a class="tag-link-613" href="http://dataunion.org/category/industry/case" style="font-size: 16.984251968504pt;" title="84个话题">
        行业应用
       </a>
       <a class="tag-link-885" href="http://dataunion.org/category/industry/news" style="font-size: 17.425196850394pt;" title="102个话题">
        行业资讯
       </a>
       <a class="tag-link-10" href="http://dataunion.org/category/training" style="font-size: 14.228346456693pt;" title="26个话题">
        课程
       </a>
       <a class="tag-link-16" href="http://dataunion.org/category/sources" style="font-size: 15.661417322835pt;" title="48个话题">
        资源
       </a>
      </div>
     </div>
     <div class="sitebar_list">
      <h4 class="sitebar_title">
       功能
      </h4>
      <ul>
       <li>
        <a href="http://dataunion.org/wp-login.php?action=register">
         注册
        </a>
       </li>
       <li>
        <a href="http://dataunion.org/wp-login.php">
         登录
        </a>
       </li>
       <li>
        <a href="http://dataunion.org/feed">
         文章
         <abbr title="Really Simple Syndication">
          RSS
         </abbr>
        </a>
       </li>
       <li>
        <a href="http://dataunion.org/comments/feed">
         评论
         <abbr title="Really Simple Syndication">
          RSS
         </abbr>
        </a>
       </li>
       <li>
        <a href="https://cn.wordpress.org/" title="基于WordPress，一个优美、先进的个人信息发布平台。">
         WordPress.org
        </a>
       </li>
      </ul>
     </div>
    </aside>
    <div class="clear">
    </div>
   </div>
   <!--main-->
   ﻿
   <footer id="dibu">
    <div class="about">
     <div class="right">
      <ul class="menu" id="menu-%e5%ba%95%e9%83%a8%e8%8f%9c%e5%8d%95">
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-18024" id="menu-item-18024">
        <a href="http://dataunion.org/category/partners">
         合作伙伴
        </a>
       </li>
       <li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-20881" id="menu-item-20881">
        <a href="http://dataunion.org/contribute">
         文章投稿
        </a>
       </li>
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-20872" id="menu-item-20872">
        <a href="http://dataunion.org/category/%e5%8a%a0%e5%85%a5%e6%95%b0%e7%9b%9f">
         加入数盟
        </a>
       </li>
       <li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-22441" id="menu-item-22441">
        <a href="http://dataunion.org/f-links">
         友情链接
        </a>
       </li>
       <li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-20874" id="menu-item-20874">
        <a href="http://dataunion.org/aboutus">
         关于数盟
        </a>
       </li>
      </ul>
      <p class="banquan">
       数盟社区        ，
        做最棒的数据科学社区
      </p>
     </div>
     <div class="left">
      <ul class="bottomlist">
       <li>
        <a href="http://weibo.com/DataScientistUnion  " target="_blank" 　title="">
         <img src="http://dataunion.org/wp-content/themes/yzipi/images/weibo.png"/>
        </a>
       </li>
       <li>
        <a class="cd-popup-trigger" href="http://dataunion.org/19795.html#0">
         <img src="http://dataunion.org/wp-content/themes/yzipi/images/weixin.png"/>
        </a>
       </li>
      </ul>
      <div class="cd-popup">
       <div class="cd-popup-container">
        <h1>
         扫描二维码,加微信公众号
        </h1>
        <img src="http://dataunion.org/wp-content/themes/yzipi/images/2014-12-06-1515289049.png"/>
        <a class="cd-popup-close" href="http://dataunion.org/19795.html">
        </a>
       </div>
       <!-- cd-popup-container -->
      </div>
      <!-- cd-popup -->
     </div>
    </div>
    <!--about-->
    <div class="bottom">
     <a href="http://dataunion.org/">
      数盟社区
     </a>
     <a href="http://www.miitbeian.gov.cn/" rel="external nofollow" target="_blank">
      京ICP备14026740号
     </a>
     联系我们：
     <a href="mailto:contact@dataunion.org" target="_blank">
      contact@dataunion.org
     </a>
     <div class="tongji">
     </div>
     <!--bottom-->
     <div class="scroll" id="scroll" style="display:none;">
      ︿
     </div>
    </div>
   </footer>
   <!--dibu-->
  </div>
 </body>
</html>